package com.iceframework.core.activiti.service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.iceframework.core.activiti.entity.BpmsActivityTypeEnum;
import com.iceframework.core.activiti.entity.UtilMisc;

@Service
public class ActivitiService {

	@Autowired
	private RuntimeService runtimeService;
	@Autowired
	private TaskService taskService;
	@Autowired
	private HistoryService historyService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private ProcessEngineConfigurationImpl processEngineConfiguration;

	/**
	 * 启动流程
	 * 
	 */
	public String startProcesses(String type) {
		ProcessInstance pi = runtimeService.startProcessInstanceByKey(type);// 流程图id，业务表id
		return pi.getId();
	}
	
	/**
	 * 启动流程
	 * @param type
	 * @param params
	 * @return
	 */
	public String startProcesses(String type,Map<String,Object> params) {
		ProcessInstance pi = runtimeService.startProcessInstanceByKey(type);// 流程图id，业务表id
		runtimeService.startProcessInstanceByKey(pi.getProcessDefinitionKey(), params);// 流程图id，业务表id
		return pi.getId();
	}

	/**
	 * 描述: 根据用户id查询待办任务列表
	 * 
	 * @param type
	 * @param userId
	 * @return
	 */
	public List<Task> findTasksByUserId(String type, String userId) {
		List<Task> resultTask = taskService.createTaskQuery().processDefinitionKey(type).taskCandidateOrAssigned(userId)
				.list();
		return resultTask;
	}

	/**
	 * 描述:任务审批 （通过/拒接）
	 * 
	 * @param taskId
	 * @param userId
	 * @param result
	 */
	public void completeTask(String taskId, String userId, Map<String, Object> params) {
		// 获取流程实例
		taskService.claim(taskId, userId);
		taskService.complete(taskId, params);
	}

	/**
	 * 更改业务流程状态
	 * 
	 * @param execution
	 * @param status
	 */
	public void updateBizStatus(DelegateExecution execution, String status) {
		String bizId = execution.getProcessInstanceBusinessKey();
		this.updateBizStatus(execution,status);
		// 根据业务id自行处理业务表
		System.out.println("业务表[" + bizId + "]状态更改成功，状态更改为：" + status);
	}

	/**
	 * 生成图片
	 * @param id
	 * @return
	 */
	public InputStream getResourceDiagramInputStream(String processInstanceId) {
		try {
			// 获取历史流程实例
			HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
					.processInstanceId(processInstanceId).singleResult();

			// 获取流程中已经执行的节点，按照执行先后顺序排序
			List<HistoricActivityInstance> historicActivityInstanceList = historyService
					.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceId()
					.asc().list();

			// 构造已执行的节点ID集合
			List<String> executedActivityIdList = new ArrayList<String>();
			for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
				executedActivityIdList.add(activityInstance.getActivityId());
			}

			// 获取bpmnModel
			BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
			// 获取流程已发生流转的线ID集合
			List<String> flowIds = this.getExecutedFlows(bpmnModel, historicActivityInstanceList);

			// 使用默认配置获得流程图表生成器，并生成追踪图片字符流
			ProcessDiagramGenerator processDiagramGenerator = processEngineConfiguration.getProcessEngineConfiguration()
					.getProcessDiagramGenerator();
			InputStream imageStream = processDiagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList,
					flowIds, "宋体", "微软雅黑", "黑体", null, 2.0);
			return imageStream;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	private List<String> getExecutedFlows(BpmnModel bpmnModel,
			List<HistoricActivityInstance> historicActivityInstances) {
		// 流转线ID集合
		List<String> flowIdList = new ArrayList<String>();
		// 全部活动实例
		List<FlowNode> historicFlowNodeList = new LinkedList<FlowNode>();
		// 已完成的历史活动节点
		List<HistoricActivityInstance> finishedActivityInstanceList = new LinkedList<HistoricActivityInstance>();
		for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
			historicFlowNodeList.add((FlowNode) bpmnModel.getMainProcess()
					.getFlowElement(historicActivityInstance.getActivityId(), true));
			if (historicActivityInstance.getEndTime() != null) {
				finishedActivityInstanceList.add(historicActivityInstance);
			}
		}

		// 遍历已完成的活动实例，从每个实例的outgoingFlows中找到已执行的
		FlowNode currentFlowNode = null;
		for (HistoricActivityInstance currentActivityInstance : finishedActivityInstanceList) {
			// 获得当前活动对应的节点信息及outgoingFlows信息
			currentFlowNode = (FlowNode) bpmnModel.getMainProcess()
					.getFlowElement(currentActivityInstance.getActivityId(), true);
			List<SequenceFlow> sequenceFlowList = currentFlowNode.getOutgoingFlows();

			/**
			 * 遍历outgoingFlows并找到已已流转的 满足如下条件认为已已流转：
			 * 1.当前节点是并行网关或包含网关，则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
			 * 2.当前节点是以上两种类型之外的，通过outgoingFlows查找到的时间最近的流转节点视为有效流转
			 */
			FlowNode targetFlowNode = null;
			if (BpmsActivityTypeEnum.PARALLEL_GATEWAY.getType().equals(currentActivityInstance.getActivityType())
					|| BpmsActivityTypeEnum.INCLUSIVE_GATEWAY.getType()
							.equals(currentActivityInstance.getActivityType())) {
				// 遍历历史活动节点，找到匹配Flow目标节点的
				for (SequenceFlow sequenceFlow : sequenceFlowList) {
					targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(),
							true);
					if (historicFlowNodeList.contains(targetFlowNode)) {
						flowIdList.add(sequenceFlow.getId());
					}
				}
			} else {
				List<Map<String, String>> tempMapList = new LinkedList<Map<String, String>>();
				// 遍历历史活动节点，找到匹配Flow目标节点的
				for (SequenceFlow sequenceFlow : sequenceFlowList) {
					for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
						if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
							tempMapList.add(UtilMisc.toMap("flowId", sequenceFlow.getId(), "activityStartTime",
									String.valueOf(historicActivityInstance.getStartTime().getTime())));
						}
					}
				}

				// 遍历匹配的集合，取得开始时间最早的一个
				long earliestStamp = 0L;
				String flowId = null;
				for (Map<String, String> map : tempMapList) {
					long activityStartTime = Long.valueOf(map.get("activityStartTime"));
					if (earliestStamp == 0 || earliestStamp >= activityStartTime) {
						earliestStamp = activityStartTime;
						flowId = map.get("flowId");
					}
				}
				flowIdList.add(flowId);
			}
		}
		return flowIdList;
	}
}